1 00:00:00,370 --> 00:00:01,270 Welcome back. 2 00:00:01,270 --> 00:00:05,740 We're going to jump right into this lecture by starting to script our client sided drink class. 3 00:00:05,740 --> 00:00:07,480 So let's go ahead and get started. 4 00:00:07,480 --> 00:00:12,010 The services we're going to need in our client side of drink class of course is going to be replicated 5 00:00:12,010 --> 00:00:12,820 storage. 6 00:00:12,820 --> 00:00:16,270 That way we can reference all of the assets for our SCP. 7 00:00:17,360 --> 00:00:22,280 We're going to need the run service as well to verify that whatever script is requiring this module 8 00:00:22,280 --> 00:00:24,200 script is running on the client. 9 00:00:24,890 --> 00:00:30,410 We're going to need the tween service, and we're going to use this to tween some GUI elements for, 10 00:00:30,410 --> 00:00:32,600 you know, the drink messages on the screen. 11 00:00:33,360 --> 00:00:38,430 And of course, we're going to have the player service to refer to the local player when we need to. 12 00:00:39,880 --> 00:00:44,590 Now, some variables we're going to need, of course, is to check whether or not the script is running 13 00:00:44,590 --> 00:00:45,340 on the client. 14 00:00:45,340 --> 00:00:46,990 So I'm calling it is client. 15 00:00:46,990 --> 00:00:50,350 And inside the run service there's a function for is client. 16 00:00:50,860 --> 00:00:55,240 If this got required by the server for some reason then we're just going to return an empty table and 17 00:00:55,240 --> 00:00:55,870 that's it. 18 00:00:56,990 --> 00:01:01,700 Otherwise we can set up the same thing like we did in our server class. 19 00:01:01,850 --> 00:01:07,100 We'll have a table to represent the class and a meta table to hold all the functions. 20 00:01:07,980 --> 00:01:12,780 And we'll make sure to set the underscore underscore index meta method to the drink meta table. 21 00:01:13,970 --> 00:01:19,040 And then we're going to refer to things like the request event, which is in replicated storage. 22 00:01:19,040 --> 00:01:24,740 And since we're on the client and I plan to have this module script get required by the local script 23 00:01:24,740 --> 00:01:29,990 that's in the GUI, and since that's in the starter GUI, we don't know if this is going to be replicated 24 00:01:29,990 --> 00:01:30,470 right away. 25 00:01:30,470 --> 00:01:34,190 So we're going to wait for this SCP 294 assets folder. 26 00:01:34,190 --> 00:01:39,530 And then we're also going to wait for the request remote function in case it hasn't been replicated. 27 00:01:40,380 --> 00:01:42,150 We'll do the same thing for comms event. 28 00:01:43,580 --> 00:01:49,100 Remember, we don't have to wait for that folder again because we did it right here and get the comms 29 00:01:49,100 --> 00:01:49,640 event. 30 00:01:50,960 --> 00:01:56,000 I'm also going to have a table in here called Current Drinks, and this is going to store all of the 31 00:01:56,000 --> 00:01:57,590 drinks that exist on the client. 32 00:01:57,590 --> 00:02:02,120 So any drink that the player has in their inventory, the objects for those drinks are going to be stored 33 00:02:02,120 --> 00:02:02,990 in this table. 34 00:02:02,990 --> 00:02:05,090 So we'll have a separate one here on the client. 35 00:02:05,090 --> 00:02:09,170 And the server has one on its end as well right here. 36 00:02:09,320 --> 00:02:14,180 And then I'm also going to require that module script that stores all the functions for the drinks. 37 00:02:14,180 --> 00:02:15,920 So I'll call it drink functions. 38 00:02:15,920 --> 00:02:20,480 We're going to require and replicated storage dot SCP 294 assets. 39 00:02:21,140 --> 00:02:26,150 We're going to wait for the server side drink class, because a child of that drink class is going to 40 00:02:26,150 --> 00:02:28,340 be the pre-made drink functions. 41 00:02:28,340 --> 00:02:32,930 And that's the module script we're going to require, just in case we need to execute any functionality 42 00:02:32,930 --> 00:02:34,520 for some specific drinks. 43 00:02:34,520 --> 00:02:39,980 And lastly, we're also going to create a new RNG data type. 44 00:02:41,550 --> 00:02:42,120 All right. 45 00:02:42,120 --> 00:02:46,590 So now the only private functions we're going to need in here are actually ones we've already created. 46 00:02:46,590 --> 00:02:49,170 So it can go to our drink class on the server. 47 00:02:49,170 --> 00:02:51,600 And we can just copy these two. 48 00:02:52,120 --> 00:02:57,670 Functions right here and paste those into here, because these are going to be the exact same functions 49 00:02:57,670 --> 00:02:59,470 we're going to need here on the client. 50 00:02:59,800 --> 00:03:01,630 We're going to check arguments. 51 00:03:01,630 --> 00:03:05,710 And we're also going to be able to destroy drink objects on the client as well. 52 00:03:05,980 --> 00:03:12,460 Some other private functions we're going to need are for some events we'll use on the cup tool itself. 53 00:03:12,460 --> 00:03:16,870 So we want to listen for when that cup tool gets equipped, when it gets unequipped and when it gets 54 00:03:16,870 --> 00:03:17,740 activated. 55 00:03:17,740 --> 00:03:22,960 That way, you know, we can play animations and we can consume the drink when the player activates 56 00:03:22,960 --> 00:03:23,770 the tool. 57 00:03:23,770 --> 00:03:27,160 So we'll have one function, we'll call it on equipped. 58 00:03:27,160 --> 00:03:30,640 And this is going to be for when our drink cup gets equipped. 59 00:03:31,620 --> 00:03:35,550 We're going to have a function for when it gets unequipped. 60 00:03:35,730 --> 00:03:40,200 So we'll call it on unequipped pass self to it as well. 61 00:03:41,520 --> 00:03:44,010 We're going to have a function for when the drink gets activated. 62 00:03:44,010 --> 00:03:47,130 So on activated again we'll pass self. 63 00:03:48,450 --> 00:03:53,580 And then one more function I want to have is to fade that message. 64 00:03:53,580 --> 00:03:57,690 Like when we drink the liquid out of our cup, we're going to get that message on the bottom of the 65 00:03:57,690 --> 00:04:02,070 screen that tells us what's going on, gives us context for the drink, so we can call this function 66 00:04:02,070 --> 00:04:04,500 fade DUI message. 67 00:04:04,500 --> 00:04:06,240 Again, we're going to pass self to it. 68 00:04:06,240 --> 00:04:10,290 And in here is where we'll, you know, fade out the text or fade in the text. 69 00:04:10,290 --> 00:04:16,050 Set the text to be, you know, whatever is for the specific object or cup that's being consumed and 70 00:04:16,050 --> 00:04:16,830 stuff like that. 71 00:04:17,370 --> 00:04:21,510 Now, instead of public functions, we're going to create a new constructor. 72 00:04:21,510 --> 00:04:26,040 But this constructor is going to be a little bit different than the one that's going to be on our server 73 00:04:26,040 --> 00:04:26,670 script. 74 00:04:26,850 --> 00:04:31,500 Specifically, we don't have to create a new type in here, because the only thing I want to pass to 75 00:04:31,500 --> 00:04:37,350 this constructor one is going to be the guy that's going to contain the text we need to update on the 76 00:04:37,350 --> 00:04:39,510 screen for our UI message. 77 00:04:39,510 --> 00:04:43,290 So we need to pass a UI to this function, which is a screen UI. 78 00:04:44,410 --> 00:04:47,950 We're also going to need the drink name that the player inputted. 79 00:04:47,980 --> 00:04:51,880 That way, we can create a new object based on the name of the drink we entered. 80 00:04:51,880 --> 00:04:54,850 So if they want a cup of air, they'll pass air here. 81 00:04:54,850 --> 00:05:01,150 And then we can use the remote function to invoke the server to create a new drink object, and then 82 00:05:01,150 --> 00:05:03,160 get that object back here on the client. 83 00:05:03,160 --> 00:05:08,260 And using that new drink object, we can attach all of the client side stuff to it for us. 84 00:05:08,620 --> 00:05:11,710 And then the last thing I'll need is an optional parameter. 85 00:05:11,710 --> 00:05:12,880 I'm going to call it ID. 86 00:05:13,360 --> 00:05:18,130 And this is going to be optional because there might be a time where we need to use this constructor 87 00:05:18,130 --> 00:05:24,550 to either a create a new drink and get that drink from the server, or b create a new drink object on 88 00:05:24,550 --> 00:05:25,360 the client. 89 00:05:25,360 --> 00:05:29,740 But that drink object already exists on the server and we just need to get it on the client. 90 00:05:29,920 --> 00:05:31,570 So let's go ahead and start filling this out. 91 00:05:31,570 --> 00:05:37,150 We're obviously going to check the argument guy to make sure it is of the type screen guy or of the 92 00:05:37,150 --> 00:05:38,890 class screen guy. 93 00:05:39,420 --> 00:05:45,420 We're going to check our drink name just to make sure you know it is indeed a string. 94 00:05:45,980 --> 00:05:50,030 And then we're not going to check the ID because it's an optional parameter. 95 00:05:50,180 --> 00:05:55,130 But what we're going to do here is I'm going to create two variables. 96 00:05:55,130 --> 00:05:57,620 I'm going to call one success and result. 97 00:05:57,620 --> 00:06:01,340 And this is going to store the information that gets returned from our remote function. 98 00:06:02,120 --> 00:06:06,860 And then what I'm going to do now is I'm going to check if we were passed an ID to our constructor. 99 00:06:07,250 --> 00:06:14,660 So if we were not passed an ID aka id is nil, then what we could do is we could set success and result 100 00:06:14,660 --> 00:06:16,610 equal to the request event. 101 00:06:16,610 --> 00:06:19,580 And we're going to invoke the server to do a particular action. 102 00:06:19,580 --> 00:06:23,990 And that action is create and get a drink object. 103 00:06:23,990 --> 00:06:31,160 So remember here in our server script, if we go down to our remote function we have the ability to 104 00:06:31,160 --> 00:06:33,140 create and get a drink object. 105 00:06:33,140 --> 00:06:37,550 So it's going to go in there and create a drink object gives it a player. 106 00:06:37,550 --> 00:06:39,920 And then the key for the drink. 107 00:06:40,600 --> 00:06:44,470 So that means we're going to have to pass the drink name, which is also the key. 108 00:06:44,770 --> 00:06:49,210 Otherwise we can put an else statement here, meaning that we did get passed an ID. 109 00:06:49,360 --> 00:06:54,910 And if this constructor gets passed an ID, then that means we automatically know that there's an object 110 00:06:54,910 --> 00:06:57,820 that already exists on the server with this particular ID. 111 00:06:57,940 --> 00:07:03,760 So instead we could set success and result equal to the request event. 112 00:07:03,760 --> 00:07:06,940 And we're going to invoke server request. 113 00:07:06,970 --> 00:07:09,490 The action is request drink object. 114 00:07:09,490 --> 00:07:11,530 So we're not creating a new drink object. 115 00:07:11,530 --> 00:07:13,330 We're just getting one that already exists. 116 00:07:13,330 --> 00:07:15,760 And remember we need to pass them that ID. 117 00:07:16,120 --> 00:07:21,910 So inside of here in our remote function we can request a drink object right here. 118 00:07:21,910 --> 00:07:23,770 And we pass to them the ID. 119 00:07:23,770 --> 00:07:28,540 And we can check to see on the server if that object exists and whether or not the player is supposed 120 00:07:28,540 --> 00:07:29,440 to be the owner of it. 121 00:07:29,440 --> 00:07:32,740 And if they are, then we'll return the object back to them on the client. 122 00:07:33,160 --> 00:07:39,400 Now, the way I plan to set this up is that every time a cup or a cup tool gets added to the backpack 123 00:07:39,400 --> 00:07:45,250 of a player, we're going to have a function that's listening to whenever it gets added, and then it's 124 00:07:45,250 --> 00:07:49,840 going to request to get the drink object for that specific drink cup based on the ID. 125 00:07:50,140 --> 00:07:55,990 However, we don't want to do that if we've already gotten the object on the client. 126 00:07:55,990 --> 00:08:01,060 So for example, when we create a new drink object on the server and we give it to the player in their 127 00:08:01,060 --> 00:08:06,370 inventory, then that function will fire and get the object on the client, and we'll store it inside 128 00:08:06,370 --> 00:08:07,930 of our current drinks table. 129 00:08:08,050 --> 00:08:10,900 But let's say they equip it and then unequip it. 130 00:08:10,900 --> 00:08:14,920 Well, that means that event's going to get fired again, because that drink cup got re-added back into 131 00:08:14,920 --> 00:08:15,730 our inventory. 132 00:08:15,730 --> 00:08:18,670 And we don't want to create, you know, another drink object. 133 00:08:18,820 --> 00:08:27,310 So the plan is before we set success and result, we need to check whether or not that our drink exists 134 00:08:27,310 --> 00:08:30,100 within our current drinks function. 135 00:08:30,100 --> 00:08:34,930 And the way we could do that is we could copy a function from our drink class on the server, which 136 00:08:34,930 --> 00:08:38,530 is the get object from ID. 137 00:08:38,530 --> 00:08:41,950 So we're going to copy this and put this here in our function. 138 00:08:41,950 --> 00:08:43,930 So this is going to do the exact same thing. 139 00:08:43,930 --> 00:08:47,560 It's going to loop through our current drinks table on the client side. 140 00:08:47,560 --> 00:08:50,710 And it's going to check if we already have a drink object with that ID. 141 00:08:50,710 --> 00:08:53,950 If we do then we don't have to request another drink object. 142 00:08:53,950 --> 00:08:54,910 We already have it. 143 00:08:55,620 --> 00:08:58,530 So we could set result equal to drink. 144 00:08:58,650 --> 00:09:03,030 Get object from id and pass the id that gets passed to our constructor. 145 00:09:03,030 --> 00:09:07,500 And if we already have a result, aka we already have the object on the client, then we're just going 146 00:09:07,500 --> 00:09:09,900 to return and do nothing with this constructor. 147 00:09:09,930 --> 00:09:15,570 Another thing we're going to have to watch out for is in case the invoke server function errors and 148 00:09:15,570 --> 00:09:19,590 success is set to false, meaning some error happened so we could check. 149 00:09:19,590 --> 00:09:28,650 If not success, then we can just warn on the client and we'll create a string unable to create or get 150 00:09:28,650 --> 00:09:31,680 drink object on client. 151 00:09:31,680 --> 00:09:35,730 And then we can say the error is we'll pass a directive here for a string. 152 00:09:36,060 --> 00:09:42,690 And that means we can wrap this string in parentheses and call the format function on it. 153 00:09:42,930 --> 00:09:45,150 And what's going to replace that directive. 154 00:09:45,150 --> 00:09:49,440 Well the result from the invoke server function which should be an error message. 155 00:09:49,440 --> 00:09:50,790 So for example. 156 00:09:51,790 --> 00:09:54,970 Inside of our on server invoke function. 157 00:09:55,420 --> 00:09:59,500 If we try to do something in here, let's say we accidentally pass, you know, the wrong action or 158 00:09:59,500 --> 00:09:59,920 something. 159 00:09:59,920 --> 00:10:02,650 It's going to return false and give us an error message here. 160 00:10:02,650 --> 00:10:08,590 And we're going to take that string and we're going to put it in here using the format function. 161 00:10:08,590 --> 00:10:12,640 So that way it's a little bit easier for us to debug problems on the client. 162 00:10:12,640 --> 00:10:17,380 And of course we don't want to forget to return because the Warn function will not halt the thread of 163 00:10:17,380 --> 00:10:18,340 execution. 164 00:10:18,340 --> 00:10:24,520 Otherwise, if everything checks out good, then we can set the self variable equal to the result from 165 00:10:24,520 --> 00:10:26,830 either this function or this function. 166 00:10:26,920 --> 00:10:29,710 Whichever action returns to us our drink object. 167 00:10:29,800 --> 00:10:35,380 And because of that limitation I talked about in the previous lecture, where the meta table, when 168 00:10:35,380 --> 00:10:39,940 it gets passed through remote functions or remote events, the meta table is lost. 169 00:10:39,940 --> 00:10:45,850 So that means we're going to have to reattach a new meta table to our object, which is going to contain 170 00:10:45,850 --> 00:10:47,560 all the functions on the client. 171 00:10:47,560 --> 00:10:48,970 And that's pretty easy to do. 172 00:10:48,970 --> 00:10:55,180 All we can do is call the set meta table function pass self, and then attach our drink meta table here 173 00:10:55,180 --> 00:10:56,290 on the client. 174 00:10:56,830 --> 00:11:02,170 And now this drink object on the client is going to have access to all the client related functions. 175 00:11:02,170 --> 00:11:10,060 Now another thing I want to do is I want to get a reference to the animator that is inside of the players, 176 00:11:10,060 --> 00:11:11,230 uh, humanoid. 177 00:11:11,230 --> 00:11:18,130 So what we could do is that since this object is automatically going to have the properties from the 178 00:11:18,130 --> 00:11:23,590 server, which is going to be all of these, we can get the owner property as well. 179 00:11:23,590 --> 00:11:27,910 So we could do self dot owner get their character. 180 00:11:27,910 --> 00:11:34,810 And this is referring to the local player or us get our humanoid and then get the animator inside of 181 00:11:34,810 --> 00:11:35,530 our humanoid. 182 00:11:35,530 --> 00:11:40,420 And then using this animator we can load the animations that are in our drink cup. 183 00:11:40,870 --> 00:11:45,850 So let's set up some other properties for our object on the client. 184 00:11:46,210 --> 00:11:51,070 So first I want to have a reference to the guy that's going to contain our drink label. 185 00:11:51,070 --> 00:11:57,010 So we'll just do self dot guy is equal to the guy that gets passed to this function. 186 00:11:57,490 --> 00:12:02,950 We're going to have a debounce in here that keeps track of whether or not we've already drank our cup 187 00:12:02,950 --> 00:12:07,600 on the client, so we'll call it drink Debounce and we'll set it to false as default. 188 00:12:08,170 --> 00:12:13,330 And then from here we can load the animations, which will be our idle track for our drink cup and our 189 00:12:13,330 --> 00:12:15,130 consumption track for our drink cup. 190 00:12:15,130 --> 00:12:20,380 So one will be idle track, and we're going to use the animator to load an animation. 191 00:12:20,380 --> 00:12:25,420 And actually let's use type annotation and denote this as an animator. 192 00:12:25,480 --> 00:12:28,360 So that way we can actually see all the functions. 193 00:12:28,360 --> 00:12:33,610 There we go load animation and we're going to pass self dot cup. 194 00:12:33,730 --> 00:12:35,320 And inside of our cup. 195 00:12:35,320 --> 00:12:40,330 If you remember there's a folder for animations and we have our two animations in there. 196 00:12:40,330 --> 00:12:43,210 So self dot cup get the animations folder. 197 00:12:43,570 --> 00:12:45,430 And this is going to be the idle animation. 198 00:12:45,430 --> 00:12:48,340 So we're loading this animation on our humanoid. 199 00:12:48,340 --> 00:12:53,440 And then we could do the same thing for the consume track or the consume animation. 200 00:12:53,440 --> 00:12:55,810 We'll get a track back from this function. 201 00:12:55,810 --> 00:12:59,230 Self dot cup dot animations dot consume. 202 00:13:00,050 --> 00:13:03,020 The next thing I want to do is I want to create a new table in here. 203 00:13:03,020 --> 00:13:04,820 I'm going to call it connections. 204 00:13:05,210 --> 00:13:12,380 And this table is going to store all the instances that get returned from the connect function. 205 00:13:12,380 --> 00:13:17,450 So, you know, when we listen to events specifically we're going to be listening to events on the tool. 206 00:13:17,540 --> 00:13:23,180 It's going to return an object back to us that is used to, you know, listen to that specific event 207 00:13:23,180 --> 00:13:28,130 and we're able to connect or disconnect that, uh, function to that particular event. 208 00:13:28,130 --> 00:13:32,150 And when the cup gets destroyed, we want to, you know, disconnect those events. 209 00:13:32,990 --> 00:13:39,200 So inside of self dot connections we can have an event for when the cup gets activated. 210 00:13:39,200 --> 00:13:41,420 I'll just create a new key value pair. 211 00:13:41,420 --> 00:13:42,620 I'll call it activated. 212 00:13:43,130 --> 00:13:48,200 And at this key we're going to store self dot cup dot activated. 213 00:13:48,810 --> 00:13:53,430 Activated, we're going to connect a function to it. 214 00:13:53,670 --> 00:13:57,270 And this function is going to call the on activated function. 215 00:13:57,270 --> 00:13:59,460 And we're going to pass the object to it. 216 00:14:00,090 --> 00:14:02,370 And remember, this function is going to return to us. 217 00:14:02,370 --> 00:14:06,180 I believe it's an R script connection or event connection. 218 00:14:06,180 --> 00:14:08,250 It's something like that, some kind of instance. 219 00:14:08,250 --> 00:14:13,290 And we can use that instance to disconnect this lambda function from this particular event when we need 220 00:14:13,290 --> 00:14:13,740 to. 221 00:14:14,130 --> 00:14:17,550 And then we could do the same thing for all of the other events we need to listen to. 222 00:14:17,580 --> 00:14:20,010 We need to listen for when our cup gets equipped. 223 00:14:20,010 --> 00:14:26,700 So at this key value pair, we can just store cup dot equipped and connect a lambda function that calls 224 00:14:26,700 --> 00:14:29,520 the on equip function pass self to it. 225 00:14:32,490 --> 00:14:36,480 And we'll do one for the unequipped event as well. 226 00:14:43,440 --> 00:14:46,860 Past self and put the end statement. 227 00:14:47,310 --> 00:14:49,260 And I think that's all we need to do. 228 00:14:49,260 --> 00:14:52,710 So the last thing we must complete is to insert. 229 00:14:53,450 --> 00:14:57,590 This new drink object on the client into our current drinks table. 230 00:14:57,980 --> 00:15:03,170 So now that we have this connections table here, there's actually a modification that I want to make 231 00:15:03,170 --> 00:15:05,990 to our destroy drink object. 232 00:15:06,140 --> 00:15:10,640 And I want to loop through that table and disconnect all of these connections. 233 00:15:10,670 --> 00:15:16,190 Now that's not going to be an issue because when we destroy our drink object, we're actually destroying 234 00:15:16,190 --> 00:15:21,500 the cup on the client as well as on the server, which automatically destroys all of the connections 235 00:15:21,500 --> 00:15:24,290 that we've attached to the cup and its specific events. 236 00:15:24,290 --> 00:15:29,570 But just in case we have maybe other connections in here for some events that aren't related to the 237 00:15:29,570 --> 00:15:32,630 Cup, we want to disconnect those functions. 238 00:15:33,510 --> 00:15:34,980 So what we can do. 239 00:15:36,120 --> 00:15:40,230 Is we can loop through every single key value pair inside of that table. 240 00:15:40,230 --> 00:15:45,120 So we'll call this connection in pairs self dot connections. 241 00:15:46,600 --> 00:15:50,620 And what we're going to do is we're going to get that connection and just disconnect it. 242 00:15:53,560 --> 00:15:55,930 And in fact, we're going to do the same thing on the server. 243 00:15:55,930 --> 00:16:01,270 But that's going to be in a later lecture because we're going to have to disconnect a specific event. 244 00:16:01,270 --> 00:16:04,840 You might remember what that event is, but we're going to get to that later. 245 00:16:04,840 --> 00:16:08,470 So don't worry about disconnecting events on the server class for now. 246 00:16:08,470 --> 00:16:11,710 Instead, let's go ahead and fill out these functions down here. 247 00:16:12,100 --> 00:16:16,360 These ones should be pretty easy to fill out, because all I want to do when the cup gets equipped is 248 00:16:16,360 --> 00:16:22,450 to play our idle track, so we can refer to self and get the idle track property that we created in 249 00:16:22,450 --> 00:16:22,900 there. 250 00:16:22,900 --> 00:16:25,180 And then we can just call the play function on it. 251 00:16:25,690 --> 00:16:29,290 So now we'll be holding our cup just the way we want to. 252 00:16:29,290 --> 00:16:33,460 And when we unequip our cup then we can just stop the idle track. 253 00:16:33,910 --> 00:16:40,060 And then when our cup gets activated, what we could do is we'll have a function in here for consuming 254 00:16:40,060 --> 00:16:40,450 it. 255 00:16:40,450 --> 00:16:42,910 So we'll have a function to consume the drink. 256 00:16:43,470 --> 00:16:47,460 And we'll go ahead and make that in the drink meta table right now. 257 00:16:47,460 --> 00:16:48,900 So we'll call it consume. 258 00:16:50,090 --> 00:16:54,710 So whenever our cup gets activated, we'll call the consume event and play. 259 00:16:54,710 --> 00:16:59,240 You know, the consume, drinking, animation and all that kind of fun stuff. 260 00:16:59,690 --> 00:17:03,590 Now what do I want to do inside of our fade guy message function? 261 00:17:03,620 --> 00:17:09,710 Well, first off, I want to get a reference to the text label that's going to store the text we want 262 00:17:09,710 --> 00:17:11,150 to display on the screen. 263 00:17:11,150 --> 00:17:14,090 And that's going to be equal to self dot g. 264 00:17:14,120 --> 00:17:16,040 Remember we made the G property. 265 00:17:16,220 --> 00:17:21,950 And inside of our 294 guy there is a text label in here called drink message label. 266 00:17:21,950 --> 00:17:25,040 So we'll do dot drink message label. 267 00:17:25,430 --> 00:17:28,340 And we'll denote this as a text label. 268 00:17:28,340 --> 00:17:33,770 Because the linter isn't able to figure out on its own what exactly drink message label is. 269 00:17:34,010 --> 00:17:37,520 So this function we're going to call when we consume our drink. 270 00:17:37,520 --> 00:17:42,710 And that means we need to set the text in this label and then fade that text onto the screen. 271 00:17:42,710 --> 00:17:45,680 And then after a few seconds, fade it back out again. 272 00:17:45,710 --> 00:17:51,830 However, if you remember, some of our drinks could have a table for the consume messages. 273 00:17:51,830 --> 00:17:55,370 So there could be multiple messages that our cup could display. 274 00:17:55,370 --> 00:17:56,870 So we need to make a check for that. 275 00:17:56,870 --> 00:18:03,320 So we could do if type of self dot consume message is equal to table. 276 00:18:03,320 --> 00:18:07,100 So we know that the consume message are multiple different strings. 277 00:18:07,100 --> 00:18:10,070 Then we can pick a random string to display on the screen. 278 00:18:10,430 --> 00:18:15,950 So what I'll do is I'm actually going to create a variable called a ridge message or original message. 279 00:18:15,950 --> 00:18:21,110 I'm not going to instantiate it yet, but in here I'm going to set original message equal to self dot 280 00:18:21,110 --> 00:18:22,850 consume message. 281 00:18:22,910 --> 00:18:28,280 And we're going to pick out a random message using the RNG next integer function. 282 00:18:28,730 --> 00:18:32,720 And we'll do one to the max number of self dot consume messages. 283 00:18:32,720 --> 00:18:36,290 So we pick a random string and we set that as the original message. 284 00:18:36,590 --> 00:18:41,690 Otherwise we'll just set original message equal to self dot consume message. 285 00:18:41,780 --> 00:18:48,680 And then from this point um, to fade the guy onto our screen, we first have to verify that the guy 286 00:18:48,680 --> 00:18:50,030 is completely invisible. 287 00:18:50,060 --> 00:18:54,710 So let's say the player has multiple drinks in their inventory and they already drink when previously, 288 00:18:54,710 --> 00:18:57,950 and that text label was already faded onto their screen. 289 00:18:57,950 --> 00:19:00,230 Well, that means we'll want to fade it out. 290 00:19:00,230 --> 00:19:03,140 Instead, replace the text and then fade it back in. 291 00:19:03,140 --> 00:19:08,540 So we need to check if the text label transparency is equal to one. 292 00:19:08,540 --> 00:19:11,270 So if it's completely invisible then that's good. 293 00:19:11,270 --> 00:19:15,320 We can do text label dot text equal to original message. 294 00:19:15,680 --> 00:19:19,700 And then we'll use the tween service to create a new tween on our text label. 295 00:19:20,150 --> 00:19:23,630 We can make the tween last, I don't know, just maybe one second long. 296 00:19:23,630 --> 00:19:27,950 And the thing we need to tween is the transparency of our text. 297 00:19:29,600 --> 00:19:31,460 And we need to set that to zero. 298 00:19:31,640 --> 00:19:34,430 And then we can just call the play function on this. 299 00:19:34,580 --> 00:19:39,650 So if our text is invisible, then we're going to set the text to the original message, which could 300 00:19:39,650 --> 00:19:45,230 be something like um, there is nothing in the cup, so we'll set it to there is nothing in the cup. 301 00:19:45,230 --> 00:19:48,710 And then we tween the text to be visible on the screen. 302 00:19:49,360 --> 00:19:54,790 And then afterwards we'll wait some arbitrary amount of time, like six seconds, and then we'll fade 303 00:19:54,790 --> 00:19:56,800 the text back out of the screen. 304 00:19:56,800 --> 00:19:59,200 But we'll need to put an else statement here. 305 00:19:59,200 --> 00:20:06,190 And this else statement is for let's say our drink message label is already visible on the screen, 306 00:20:06,190 --> 00:20:09,190 and a different drink has already set a message. 307 00:20:09,400 --> 00:20:14,890 Well, then we'll, um, we're going to create a tween because we need to refer to a tween event. 308 00:20:14,890 --> 00:20:16,480 So tween service create. 309 00:20:17,500 --> 00:20:19,870 And actually we can just copy the same thing here. 310 00:20:22,230 --> 00:20:23,880 And we'll not call play on it. 311 00:20:23,880 --> 00:20:28,860 But what we need to do is we need to set the text transparency to one. 312 00:20:28,860 --> 00:20:35,730 Because if the text label transparency is anything but one, which means it's visible on the screen, 313 00:20:35,730 --> 00:20:39,840 then we need to tween it to be invisible again before we can change the text. 314 00:20:39,840 --> 00:20:46,170 So we're going to play this tween, and then we're going to wait for this tween to finish before we 315 00:20:46,170 --> 00:20:47,280 change the text. 316 00:20:47,280 --> 00:20:51,930 Once it finishes then we can do text label dot text is equal to original message. 317 00:20:52,940 --> 00:20:56,510 And then we can do this exact same tween here again. 318 00:20:57,380 --> 00:20:59,210 And play it on the screen. 319 00:20:59,210 --> 00:21:03,620 And actually, a better way to do this would be to just copy this, put it here. 320 00:21:03,620 --> 00:21:08,090 And that way you don't have to copy and paste this function in the same spot. 321 00:21:08,880 --> 00:21:15,570 After that, we're going to wait for six seconds, and then after we wait for six seconds, we want 322 00:21:15,570 --> 00:21:18,150 to tween the text label to be invisible again. 323 00:21:18,180 --> 00:21:21,480 However, there is a small problem with this. 324 00:21:21,510 --> 00:21:27,660 Let's say in those six seconds we're waiting here, the player consumes another drink and that drink 325 00:21:27,660 --> 00:21:30,780 fades out the guy and sets the text to something different. 326 00:21:30,780 --> 00:21:36,060 Well, that's why I decided to store the text in a variable called Original Message, because we're 327 00:21:36,060 --> 00:21:40,920 going to compare if the message inside of the text label is still the same. 328 00:21:41,160 --> 00:21:46,980 So if the text label and we're going to check the text transparency first. 329 00:21:47,660 --> 00:21:50,720 So if the text label is still visible. 330 00:21:51,300 --> 00:21:57,600 And the text label dot text is still equal to the original message, meaning that no other drink changed 331 00:21:57,600 --> 00:22:00,990 the message on the screen or faded out the guy. 332 00:22:01,170 --> 00:22:07,200 Then we're in the clear to go ahead and fade out the guy so we can again just copy this function here, 333 00:22:07,200 --> 00:22:10,170 and instead we're going to set the text transparency to one. 334 00:22:10,950 --> 00:22:16,140 So it's very important that we have our Fe UI function set up like this, just in case it doesn't conflict 335 00:22:16,140 --> 00:22:20,370 with any other drinks that may be fading in and out the text label on our screen. 336 00:22:20,940 --> 00:22:24,510 So let's go ahead and go back down and fill out our consume function. 337 00:22:24,540 --> 00:22:30,390 So what do we want to do when we, you know, click the drink and we try to consume it. 338 00:22:30,420 --> 00:22:35,610 Well first off before we do anything remember that drink Debounce property I made. 339 00:22:35,610 --> 00:22:37,290 We need to check if that's true. 340 00:22:37,290 --> 00:22:42,330 So if drink debounce is true, then we're just going to return because we can't drink more than one 341 00:22:42,330 --> 00:22:43,470 side of the same cup. 342 00:22:43,920 --> 00:22:46,710 Otherwise, if it isn't true, then we're going to set it to true. 343 00:22:46,710 --> 00:22:49,860 That way we can't execute this function again more than once. 344 00:22:51,130 --> 00:22:54,640 After that, we're going to have to check if the self dot is empty. 345 00:22:54,640 --> 00:22:55,840 Property is true. 346 00:22:55,870 --> 00:23:00,910 Remember on the server we have a property in there to set whether or not the drink is empty when it 347 00:23:00,910 --> 00:23:06,250 gets given to the player, because if they have a cup of air, it's going to be empty by default and 348 00:23:06,250 --> 00:23:09,940 you know you can't drink it, so there's no point playing a drinking animation. 349 00:23:10,480 --> 00:23:18,340 So instead, if the cup is empty, then what I want to do is I want to call the phage UI message function 350 00:23:18,340 --> 00:23:19,960 and pass self to it. 351 00:23:20,200 --> 00:23:24,220 After we do that, we can, you know, just destroy the cup. 352 00:23:26,710 --> 00:23:28,210 But let's say the cup isn't empty. 353 00:23:28,210 --> 00:23:34,900 Well, then, what I want to do is I want to refer to our consumed track, and I want to play that. 354 00:23:35,290 --> 00:23:43,030 And then I'm also going to wait for when an event in this consumed track gets reached. 355 00:23:43,030 --> 00:23:45,550 So let me go back to my drink animation rig here. 356 00:23:46,570 --> 00:23:48,940 And I'm going to go to the avatar tab. 357 00:23:49,030 --> 00:23:50,590 Open up my animation editor. 358 00:23:50,590 --> 00:23:55,390 When I select my drink animation rig here, you'll see that in my consume animation, I've actually 359 00:23:55,390 --> 00:23:56,920 included an event here. 360 00:23:56,920 --> 00:23:58,870 And this event is called consume. 361 00:23:59,590 --> 00:24:06,400 So I don't want to play the consume sound or do any of the effects for my drink until we hit this event 362 00:24:06,400 --> 00:24:07,420 in my animation. 363 00:24:07,950 --> 00:24:11,730 So how do we listen for when we hit that event? 364 00:24:11,760 --> 00:24:17,010 Well, there's a neat little function called git marker reached signal. 365 00:24:17,880 --> 00:24:20,760 And we can pass the name of the event which is consume. 366 00:24:21,090 --> 00:24:23,490 And we're going to wait for this event to get reached. 367 00:24:23,820 --> 00:24:30,000 Once this event gets reached then we're unclear to go ahead and do self dot consume sound and play our 368 00:24:30,000 --> 00:24:30,930 consume sound. 369 00:24:32,340 --> 00:24:35,880 And then we can also fade out our message and pass self to it. 370 00:24:36,900 --> 00:24:42,090 And then we're also going to fire to the server to consume the drink. 371 00:24:42,270 --> 00:24:46,410 That way, the liquid inside of our cup disappears for everyone in the game. 372 00:24:46,410 --> 00:24:52,980 And if you remember, our consume drink action requires for us to let me look. 373 00:24:53,790 --> 00:24:58,200 It requires for us to pass the ID of the object, which shouldn't be too difficult. 374 00:24:58,200 --> 00:24:59,790 We can just do self.id. 375 00:25:00,810 --> 00:25:06,180 And then one more thing I want to check is whether or not this drink has any functions inside of our, 376 00:25:06,180 --> 00:25:08,520 uh, drink functions module script. 377 00:25:08,520 --> 00:25:13,980 So we can check if drink functions dot current functions. 378 00:25:13,980 --> 00:25:16,020 Self dot premade key. 379 00:25:17,840 --> 00:25:24,200 So if there is a key value pair inside of the current functions for this particular drink, then we're 380 00:25:24,200 --> 00:25:26,030 going to run that function. 381 00:25:26,560 --> 00:25:31,180 So we'll do dot handler and pass the player. 382 00:25:31,820 --> 00:25:34,460 Which would be self dot owner. 383 00:25:36,180 --> 00:25:38,700 And then we'll pass the object itself. 384 00:25:38,700 --> 00:25:40,620 And in fact, this is actually a little redundant. 385 00:25:40,620 --> 00:25:43,050 We can just pass self itself. 386 00:25:43,530 --> 00:25:45,570 So let me do that on the server end as well. 387 00:25:45,570 --> 00:25:50,490 Go back to your server script for the drink class on the server. 388 00:25:50,790 --> 00:25:53,340 And when we call that handler here it is. 389 00:25:53,340 --> 00:25:57,930 Instead we can just pass the object to it because the object will have that owner property inside of 390 00:25:57,930 --> 00:25:58,380 it. 391 00:25:58,380 --> 00:26:04,470 So that means if I go back to my premade drink functions module script, I don't have to define a player 392 00:26:04,470 --> 00:26:05,010 here. 393 00:26:05,010 --> 00:26:10,980 Instead, I can just get my drink object by itself and then refer to the owner property that is inside 394 00:26:10,980 --> 00:26:12,690 of that particular drink object. 395 00:26:13,180 --> 00:26:19,720 Anyways, we'll call that function and it'll go through there and run all the code for that particular 396 00:26:19,720 --> 00:26:20,500 drink. 397 00:26:20,920 --> 00:26:29,530 Um, otherwise, if we do not have a function for that particular drink, then what I'll do is I'll 398 00:26:29,530 --> 00:26:33,640 wait for the consume track to, uh, finish animating. 399 00:26:33,640 --> 00:26:38,740 So there's an event called stop, and we're going to wait for that to fire, and we're going to wait 400 00:26:38,740 --> 00:26:41,770 for our animation to end before we destroy our drink cup. 401 00:26:42,010 --> 00:26:48,160 However, another issue you might realize is that our fade guy message function actually yields. 402 00:26:48,160 --> 00:26:52,060 Remember, we have a task dot wait six seconds in here. 403 00:26:52,060 --> 00:26:57,280 So that means when we're calling this function here, the thread of execution hops into this function 404 00:26:57,280 --> 00:27:00,790 and executes stuff in there, and it won't be able to move forward until that. 405 00:27:00,790 --> 00:27:01,180 Wait. 406 00:27:01,180 --> 00:27:02,740 Uh, six seconds is up. 407 00:27:02,740 --> 00:27:05,980 So we're actually yielding here, and we're yielding here. 408 00:27:06,520 --> 00:27:12,100 So we won't be able to actually execute the functionality for the drink or fire to the server to, you 409 00:27:12,100 --> 00:27:15,250 know, consume the drink until those six seconds are up. 410 00:27:15,250 --> 00:27:16,540 So how do we fix that? 411 00:27:16,540 --> 00:27:21,970 Well, we can just use the task dot spawn function to spawn this function in a new thread. 412 00:27:23,220 --> 00:27:24,120 So. 413 00:27:24,640 --> 00:27:31,480 We just pass a reference to our phage UI message, and then to be able to pass the object itself to 414 00:27:31,480 --> 00:27:37,570 our phage UI message function, we just pass it as a second parameter to the task spawn function. 415 00:27:37,570 --> 00:27:40,000 And then we could do the exact same thing right here. 416 00:27:40,560 --> 00:27:46,020 So the tasked spawn function is going to execute this function in a separate thread and it'll pass self 417 00:27:46,020 --> 00:27:47,250 to automatically. 418 00:27:47,640 --> 00:27:48,630 Alrighty then. 419 00:27:48,630 --> 00:27:54,180 I guess the next thing we'll have to do is define our destroy function here on the client. 420 00:27:54,630 --> 00:27:56,160 So let's go ahead and do that. 421 00:27:56,160 --> 00:28:00,030 Inside of our drink meta table we'll create a new function called destroy. 422 00:28:01,020 --> 00:28:03,660 And what do we want to do when this function gets called? 423 00:28:03,810 --> 00:28:08,790 Well, because we're going to be specifically calling this function on the client. 424 00:28:08,790 --> 00:28:13,470 That means we also want to destroy the drink object that exists on the server. 425 00:28:13,500 --> 00:28:17,910 So I'm going to create two variables, one called success and the other called result because we're 426 00:28:17,910 --> 00:28:22,410 going to call the invoke server function for our request remote function. 427 00:28:22,410 --> 00:28:23,820 So invoke server. 428 00:28:23,820 --> 00:28:28,350 The action we want the server to do is to destroy a drink object. 429 00:28:29,370 --> 00:28:35,760 And when we use that action, we need to pass the ID for that object. 430 00:28:36,030 --> 00:28:39,540 So we're going to pass self.id. 431 00:28:40,200 --> 00:28:45,450 And then we're going to check if we were successful in destroying that drink object on the server. 432 00:28:45,450 --> 00:28:52,290 If we were then we can call the destroy drink object on the client and destroy it in this module script 433 00:28:52,290 --> 00:28:53,010 as well. 434 00:28:53,580 --> 00:28:57,720 Otherwise, if we weren't successful in destroying it, then we can just print something out on the 435 00:28:57,720 --> 00:29:06,540 client and say warn unable to destroy drink object and we can give the error message using a directive. 436 00:29:06,540 --> 00:29:14,790 So again percentage S, we can wrap this string inside of parentheses and call the format function on 437 00:29:14,790 --> 00:29:15,240 it. 438 00:29:15,510 --> 00:29:18,060 And what do we want to replace at that directive. 439 00:29:18,060 --> 00:29:25,200 Well the same thing we did before which is going to be the result or AKA whatever string gets returned 440 00:29:25,200 --> 00:29:28,560 from our on server invoke function. 441 00:29:29,150 --> 00:29:29,570 All right. 442 00:29:29,570 --> 00:29:31,460 This is looking pretty good so far. 443 00:29:31,700 --> 00:29:37,340 Uh, I think the next section we can fill out is for the communication event. 444 00:29:38,150 --> 00:29:45,170 So comms event, we're going to access the on client event, uh, script signal or this event. 445 00:29:45,650 --> 00:29:47,780 And we're going to connect a function to it. 446 00:29:47,930 --> 00:29:55,370 And if you remember inside of our drink class, when we use the fire client function, we're firing 447 00:29:55,400 --> 00:30:00,770 to a specific player and we're giving them an action and then some arguments along with that action. 448 00:30:01,310 --> 00:30:05,030 So for example if the destroy function gets called on the server. 449 00:30:05,970 --> 00:30:10,050 Then we want to tell the client to destroy a particular drink object. 450 00:30:10,600 --> 00:30:16,420 So we can again define the action the server wants us to do, and then the arguments supplied to that 451 00:30:16,420 --> 00:30:17,200 action. 452 00:30:18,140 --> 00:30:24,650 And since we only have one action we're using so far, we can do if action is equal to destroy drink 453 00:30:24,650 --> 00:30:25,760 object. 454 00:30:27,310 --> 00:30:32,620 Then we can check which object they want us to destroy by getting it from the drink. 455 00:30:32,620 --> 00:30:39,520 Get object from id and pass args one, which is the ID of the object the server wants to destroy. 456 00:30:39,880 --> 00:30:47,590 If we have that object in our inventory, then what I want to do is I don't want to call object destroy. 457 00:30:47,650 --> 00:30:49,120 Why don't we want to do that? 458 00:30:49,150 --> 00:30:54,250 Well, because there's no point if the server is already telling us to destroy a drink object. 459 00:30:54,250 --> 00:30:56,530 The server already destroyed it on their end. 460 00:30:56,530 --> 00:31:01,450 And remember, in our destroy function, we're requesting for the server to destroy a drink object. 461 00:31:01,450 --> 00:31:05,770 But that object isn't going to exist if the server already deleted it, right? 462 00:31:06,330 --> 00:31:11,130 So because the server already deleted it, it's telling us to delete it on our end as well. 463 00:31:11,130 --> 00:31:16,380 So instead of using the destroy function here, we're going to use our private function destroy drink 464 00:31:16,380 --> 00:31:20,010 object instead and pass the object to that function. 465 00:31:20,630 --> 00:31:21,290 Otherwise. 466 00:31:21,290 --> 00:31:23,120 If for some reason. 467 00:31:23,680 --> 00:31:28,150 The object that the server wants us to destroy, we don't have. 468 00:31:28,150 --> 00:31:36,790 We can print something else in the console, like a drink object already destroyed, because either 469 00:31:36,790 --> 00:31:39,670 we already destroyed it or we never had it in the first place. 470 00:31:39,670 --> 00:31:44,950 And of course, in our module script, we'll want to make sure to return our drink table, which contains 471 00:31:44,950 --> 00:31:48,160 our constructor and all that kind of good stuff. 472 00:31:48,730 --> 00:31:51,610 Otherwise, I think this is looking pretty good so far. 473 00:31:51,610 --> 00:31:54,460 I think our logic is quite sound. 474 00:31:54,460 --> 00:32:00,370 Of course we aren't able to test it yet because we still have to, you know, code our local script 475 00:32:00,370 --> 00:32:02,800 that is inside of our 294 GUI. 476 00:32:02,800 --> 00:32:08,140 And we'll also have to script a server script that requires this class and sets it up. 477 00:32:08,140 --> 00:32:13,000 So we still have a little bit more work to do, but we've gotten a decent chunk of it finished. 478 00:32:13,480 --> 00:32:18,370 And before I send you off, actually, one more thing we need to do here is we can go ahead and get 479 00:32:18,370 --> 00:32:22,390 rid of our reference to the player service because in fact, actually we don't need it here on the client 480 00:32:22,390 --> 00:32:23,500 in the first place. 481 00:32:24,180 --> 00:32:24,990 Other than that. 482 00:32:24,990 --> 00:32:25,770 Hang in there. 483 00:32:25,770 --> 00:32:27,030 We're almost finished. 484 00:32:27,030 --> 00:32:28,590 I'll see you in the next lecture.